import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/utils";
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
import useUserStore from "@/store/modules/user";

import { IRspObj, TErrorCode, TOtherCode } from "./type";

let downloadLoadingInstance: { close: () => void };
// 是否显示重新登录
export let isRelogin = { show: false };

axios.defaults.headers.common["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
const service = axios.create({
	// axios中请求配置有baseURL选项，表示请求URL公共部分
	baseURL: import.meta.env.VITE_APP_BASE_API,
	// 超时
	timeout: 2 * 60000
});
const pattern =
	/[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2159]|[\u2180-\u2210]|[\u221b-\u2712]|[\u2720-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/gi;

const containsEmojiInObject = (obj: any) => {
	for (let key in obj) {
		if (typeof obj[key] === "object" && obj[key] != null) {
			// 如果值是对象，则递归处理
			containsEmojiInObject(obj[key]);
		} else if (typeof obj[key] === "string") {
			// 如果值是字符串，使用正则表达式移除emoji
			obj[key] = obj[key].replace(pattern, "");
		}
	}
};
// request拦截器
service.interceptors.request.use(
	(config: AxiosRequestConfig) => {
		// 是否需要设置 token
		const isToken = (config.headers || {}).isToken === false;
		// 是否需要防止数据重复提交
		//const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
		const isRepeatSubmit = true;
		if (getToken() && !isToken) {
			if (config.headers) {
				config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
			}
		}
		// get请求映射params参数
		if (config.method === "get" && config.params) {
			let url = config.url + "?" + tansParams(config.params);
			url = url.slice(0, -1);
			config.params = {};
			config.url = url;
		}
		if (config.data && typeof config.data === "object") {
			containsEmojiInObject(config.data);
		}
		if (!isRepeatSubmit && (config.method === "post" || config.method === "put")) {
			const requestObj = {
				url: config.url,
				data: typeof config.data === "object" ? JSON.stringify(config.data) : config.data,
				time: new Date().getTime()
			};
			const sessionObj = cache.session.getJSON("sessionObj");
			if (sessionObj === undefined || sessionObj === null || sessionObj === "") {
				cache.session.setJSON("sessionObj", requestObj);
			} else {
				const s_url = sessionObj.url; // 请求地址
				const s_data = sessionObj.data; // 请求数据
				const s_time = sessionObj.time; // 请求时间
				const interval = 1000; // 间隔时间(ms)，小于此时间视为重复提交
				if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
					const message = "数据正在处理，请勿重复提交";
					console.warn(`[${s_url}]: ` + message);
					return Promise.reject(new Error(message));
				} else {
					cache.session.setJSON("sessionObj", requestObj);
				}
			}
		}
		return config;
	},
	(error: AxiosError) => {
		console.log(error);
		Promise.reject(error);
	}
);

// 响应拦截器
service.interceptors.response.use(
	(res: AxiosResponse) => {
		// 未设置状态码则默认成功状态
		const code: TErrorCode = res.data.code || 200;
		const otherCode: TOtherCode = res.data.code;
		// 获取错误信息
		const msg = errorCode[code] || res.data.msg || errorCode["default"];
		// 二进制数据则直接返回
		if (res.request.responseType === "blob" || res.request.responseType === "arraybuffer") {
			return res.data;
		}
		if (code === 401) {
			if (!isRelogin.show) {
				isRelogin.show = true;
				ElMessageBox.confirm("登录状态已过期，您可以继续留在该页面，或者重新登录", "系统提示", {
					confirmButtonText: "重新登录",
					cancelButtonText: "取消",
					type: "warning"
				})
					.then(() => {
						isRelogin.show = false;
						useUserStore()
							.logOut()
							.then(() => {
								location.href = "/index";
							});
					})
					.catch(() => {
						isRelogin.show = false;
					});
			}
			return Promise.reject("无效的会话，或者会话已过期，请重新登录。");
		} else if (otherCode == 411) {
			return Promise.reject(res.data);
		} else if (otherCode === 500) {
			ElMessage({ message: msg, type: "error" });
			return Promise.reject(new Error(msg));
		} else if (otherCode === 601) {
			ElMessage({ message: msg, type: "warning" });
			return Promise.reject(new Error(msg));
		} else if (otherCode !== 200) {
			ElNotification.error({ title: msg });
			return Promise.reject("error");
		} else {
			return Promise.resolve(res.data);
		}
	},
	(error: AxiosError) => {
		console.log("err" + error);
		let { message } = error;
		if (message == "Network Error") {
			message = "后端接口连接异常";
		} else if (message.includes("timeout")) {
			message = "系统接口请求超时";
		} else if (message.includes("Request failed with status code")) {
			message = "系统接口" + message.substr(message.length - 3) + "异常";
		}
		ElMessage({ message: message, type: "error", duration: 5 * 1000 });
		return Promise.reject(error);
	}
);

// 通用下载方法
export function download(url: string, params: any, filename: string, config: any, renameType?: boolean) {
	downloadLoadingInstance = ElLoading.service({
		text: "正在下载数据，请稍候",
		background: "rgba(0, 0, 0, 0.7)"
	});
	return service
		.post(url, params, {
			transformRequest: [
				params => {
					return tansParams(params);
				}
			],
			headers: { "Content-Type": "application/x-www-form-urlencoded" },
			responseType: "blob",
			...config
		})
		.then(async (data: any) => {
			const isLogin = await blobValidate(data);
			if (isLogin) {
				const blob = new Blob([data]);
				if (renameType && data.type) {
					filename = filename + "." + data.type.split("/")[1];
				}
				saveAs(blob, filename);
			} else {
				const resText = await data.text();
				const rspObj: IRspObj = JSON.parse(resText);
				const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
				ElMessage.error(errMsg);
			}
			downloadLoadingInstance.close();
		})
		.catch(r => {
			console.error(r);
			ElMessage.error("下载文件出现错误，请联系管理员！");
			downloadLoadingInstance.close();
		});
}

export function download2(url: string, params: any, filename: string, config: any, renameType?: boolean) {
	downloadLoadingInstance = ElLoading.service({
		text: "正在下载数据，请稍候",
		background: "rgba(0, 0, 0, 0.7)"
	});
	return service
		.post(url, params, {
			// transformRequest: [
			// 	params => {
			// 		return tansParams(params);
			// 	}
			// ],
			headers: { "Content-Type": "application/x-www-form-urlencoded" },
			responseType: "blob",
			...config
		})
		.then(async (data: any) => {
			const isLogin = await blobValidate(data);
			if (isLogin) {
				const blob = new Blob([data]);
				if (renameType && data.type) {
					filename = filename + "." + data.type.split("/")[1];
				}
				saveAs(blob, filename);
			} else {
				const resText = await data.text();
				const rspObj: IRspObj = JSON.parse(resText);
				const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
				ElMessage.error(errMsg);
			}
			downloadLoadingInstance.close();
		})
		.catch(r => {
			console.error(r);
			ElMessage.error("下载文件出现错误，请联系管理员！");
			downloadLoadingInstance.close();
		});
}

export default service;
